package com.vxdata.utils.modules.utils.case_8x;


import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.vxdata.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Encoder;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 腾讯云天气服务
 * https://market.cloud.tencent.com/products/7404
 */
@Component
public class WeatherUtil {

    //    private static final String FIELD_SECRET_ID = "AKIDCVs4GJDlhCA97dMQRA8aSEQ2xG1diBTBAC66";//填写secretId - 孙鸿运
//    private static final String FIELD_SECRET_KEY = "gXd1rft0cx5snfa3niguisflb5h6ifko9Ds9pvtm";//填写secretKey - 孙鸿运

//    private static final String FIELD_SECRET_ID = "AKID61jLe0NZvf7b51kiuY8avFcqXqPiwtjtFq7w";//填写secretId - 公司
//    private static final String FIELD_SECRET_KEY = "F1fr8iUa616YOfn5a2iG7YsmIy862l9hEw3DB9Kg";//填写secretKey - 公司
//    private static final String FIELD_TENCENT_CLOUD_API = "https://service-is751ged-1257101137.ap-shanghai.apigateway.myqcloud.com/release/weather/query";

    @Value("${tencent.weather.field_secret_id}")
    String FIELD_SECRET_ID;
    @Value("${tencent.weather.field_secret_key}")
    String FIELD_SECRET_KEY;
    @Value("${tencent.weather.field_tencent_cloud_api}")
    String FIELD_TENCENT_CLOUD_API;

    /**
     * 获取当前小时天气
     *
     * @return
     */
    public String getHourWeather(String log, String lat, LocalDateTime time) {
        JSONObject jsonObject = getWeather(log, lat);
        if (jsonObject == null) {
            return null;
        }
        String msg = jsonObject.getString("msg");
        if (StringUtils.equals(msg, "ok")) {
            // 获取当前小时 xx:00格式
            StringBuilder hour = new StringBuilder();
            hour.append(time.getHour());
            hour.append(":00");
            JSONArray jsonArray = jsonObject.getJSONObject("result").getJSONArray("hourly");
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject obj = jsonArray.getJSONObject(i);
                if (StringUtils.equals(obj.getString("time"), hour.toString())) {
                    return obj.getString("weather");
                }
            }
        }
        return null;
    }

    /**
     * 获取天气(为了捕获异常)
     *
     * @param log
     * @param lat
     * @return
     */
    public JSONObject getWeather(String log, String lat) {
        if (StringUtils.isNotEmpty(log) && StringUtils.isNotEmpty(lat)) {
            String weatherInfo = "";
            try {
                weatherInfo = getWeatherInfo(log, lat);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            JSONObject jsonObject = JSONObject.parseObject(weatherInfo);
            return jsonObject;
        }
        return null;
    }


    /**
     * @param log 经度
     * @param lat 纬度
     * @return
     */
    private String getWeatherInfo(String log, String lat) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
        //云市场分配的密钥Id
        String secretId = FIELD_SECRET_ID;
        //云市场分配的密钥Key
        String secretKey = FIELD_SECRET_KEY;
        // url参数拼接
        String url = FIELD_TENCENT_CLOUD_API;
        String source = "market";

        Calendar cd = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        String datetime = sdf.format(cd.getTime());
        // 签名
        String auth = calcAuthorization(source, secretId, secretKey, datetime);
        // 请求方法
        String method = "GET";
        // 请求头
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("X-Source", source);
        headers.put("X-Date", datetime);
        headers.put("Authorization", auth);

        // 查询参数
        Map<String, String> queryParams = new HashMap<String, String>();
        queryParams.put("location", lat + "," + log);
        // body参数
        Map<String, String> bodyParams = new HashMap<String, String>();


        if (!queryParams.isEmpty()) {
            url += "?" + urlencode(queryParams);
        }
        String result = "";
        BufferedReader in = null;
        try {
            URL realUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            conn.setRequestMethod(method);

            // request headers
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }

            // request body
            Map<String, Boolean> methods = new HashMap<>();
            methods.put("POST", true);
            methods.put("PUT", true);
            methods.put("PATCH", true);
            Boolean hasBody = methods.get(method);
            if (hasBody != null) {
                conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

                conn.setDoOutput(true);
                DataOutputStream out = new DataOutputStream(conn.getOutputStream());
                out.writeBytes(urlencode(bodyParams));
                out.flush();
                out.close();
            }

            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;

            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    private static String calcAuthorization(String source, String secretId, String secretKey, String datetime)
            throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {
        String signStr = "x-date: " + datetime + "\n" + "x-source: " + source;
        Mac mac = Mac.getInstance("HmacSHA1");
        Key sKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), mac.getAlgorithm());
        mac.init(sKey);
        byte[] hash = mac.doFinal(signStr.getBytes("UTF-8"));
        String sig = new BASE64Encoder().encode(hash);

        String auth = "hmac id=\"" + secretId + "\", algorithm=\"hmac-sha1\", headers=\"x-date x-source\", signature=\"" + sig + "\"";
        return auth;
    }

    private static String urlencode(Map<?, ?> map) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            if (sb.length() > 0) {
                sb.append("&");
            }
            sb.append(String.format("%s=%s",
                    URLEncoder.encode(entry.getKey().toString(), "UTF-8"),
                    URLEncoder.encode(entry.getValue().toString(), "UTF-8")
            ));
        }
        return sb.toString();
    }


    public static void main(String[] args) {
        WeatherUtil weatherUtil = new WeatherUtil();
//        String weather = weatherUtil.getHourWeather("120.73100280761719", "31.264081954956055", LocalDateTime.now());
        JSONObject weather = weatherUtil.getWeather("120.73100280761719", "31.264081954956055");
        System.out.println(weather);
    }

}
